// 这里的代码价值，必须亲力亲为，自己写
// 路由守卫代码

// 导入路由
import router from '@/router'
// 导入 store
import store from '@/store'

// 导入NProgress 模块(进入页面的加载提示)
import NProgress from 'nprogress'
// 导入nprogress 的样式
import 'nprogress/nprogress.css'

// 白名单,不需要登录就可访问的
const whiteList = ['/login', '/404','/text']

// 注册路由全局前置守卫
router.beforeEach(async (to, from, next) => {
  // 开启进度加载条提示
  NProgress.start()
  // 从vuex中获取 token
  // const token = store.state.user.token
  const { token } = store.state.user
  // 判断
  if (token) {
    // 登陆了，放行
    // 如果还要去登录就没必要去了，去首页，如果要去的是404,则去404
    if (to.path === '/login') {
      // 去首页
      next('/')
      // 也需要关闭进度条
      NProgress.done()
    } else {
      // 否则放行
      // console.log('登录-->首页')
      // 获取用户信息的action在这里调用
      // 注意：
      // 1.此项目核心在权限控制，就是不同员工登录进来看到的主页菜单不同
      // 2.如果员工登录成功了，已经跳转至主页再发请求，获取员工的角色权限信息已经太晚了
      // 3.这个获取员工的角色权限信息的时机是在跳转至主页之前，拿到当前员工的角色信息，
      //   知道你是谁了，有哪些权限，然后在对应的开放左侧菜单，这些操作都做完了，再让员工跳转至主页
      //   这个时候ta所看到的左侧菜单就是ta具备的权限
      // 4.只是现在还不知道如何开放对应的左侧菜单，这个点先留着，需要去筛选路由表，以后做？？？
      //   动态筛选动态路由表即可实现

      // 这个地方代码当路由切换的时候会多次执行，会发起多次取消请求，需要优化
      // 如果没用户没有信息，才发起请求
      // 第1种解决方式：判断vuex种的userId有没有,没有去获取，有的话放行

      // 由于user模块没有做持久化，所以用户信息不回持久化，每次刷新或者重新登录都会清空，继而都会执行if里面
      if (!store.state.user.userInfo.userId) {
        // await 关键字的目的是等待action函数执行完毕，才继续往后执行（异步变同步）
        await store.dispatch('user/getUserInfoAction')
        // 这里拿到了用户信息，用户信息里有个 userInfo.roles.menus 可以拿到当前员工的角色列表
        // 这个角色列表数组中的字符串表明了当前员工可以看到左侧菜单，今后基于这个数组对动态路由表
        // 做筛选，然后调至首页，这样主页展示的左侧菜单就是当前员工能够看到的“权限”

        // 获取当前用户的menus数组
        const { menus } = store.state.user.userInfo.roles
        // console.log(menus)
        // 基于当前用户信息中, roles.menus 数组来筛选动态路由表
        // 筛选的条件：判断当前路由第一个children的名字是否在menus数组中
        // 在的话，就留下(拥有的权限/菜单)：否则就过滤掉了，舍去了（不开放）

        // const showAsyncRoutes = asyncRoutes.filter(item => menus.includes(item.children[0].name))
        // 触发route/filterAsyncRouteAction函数获取showAsyncRoutes
        // 拿到筛选后的动态路由表
        // 调用actions的函数接收返回值必须加await
        const showAsyncRoutes = await store.dispatch('route/filterAsyncRouteAction', menus)
        // console.log('showAsyncRoutes', showAsyncRoutes)

        // 把筛选的结果再动态追加到路由表中
        // router.addRoutes(路由对象数组)：同时追加多个路由规则到路由表中
        // router.addRoute(路由对象)：追加一个路由规则到路由表中
        // 把筛选的动态路由结果加入到路由表中，这样今后输入path,才能访问到component
        // 否则就算知道路由path,访问仍然会404
        router.addRoutes([...showAsyncRoutes, { path: '*', redirect: '/404', hidden: true }])
        // 刷新一下路由表，重新进入下一次
        return next({
          ...to, // 保留原有的所有要去的路由信息
          replace: true // 替换掉刚才那一次跳转的历史记录
        })
      }
      // 第2种解决方式：拿到action函数的返回值
      // const userObj = await store.dispatch('user/getUserInfoAction')
      // 判断userObj中是否存在userId,如果没有再发请求
      // 否则放行
      // if (userObj.userId) {
      // }
      // 否则放行到首页
      next()
    }
  } else {
    // 未登录，进一步判断
    // 判断要去的路由路径是否在白名单中
    // 如果在放行
    if (whiteList.includes(to.path)) {
      // 否则就跳转至登录，并携带回调地址
      next()
    } else {
      next(`/login?redirectUrl=${to.path}`)
      // 也需要关闭进度条
      NProgress.done()
    }
  }
})
// 路由全局后置守卫
router.afterEach((to, from) => {
  // 关闭进度条的加载提示
  NProgress.done()
})
// 页面/路由的访问权的核心实现思路
// 1.主页的左侧菜单是基于路由表动态生成的(控制左侧菜单的不同只需要控制路由表即可)
// 2.路由表划分为静态路由表和动态路由表，控制权限的不同就是在控制动态路由表
// 3.在路由全局前置守卫中，基于请求到的用户信息菜单menus，对动态路由表做筛选(比对路由规则的名字是否在用户菜单数组中)
// 4.把筛选的结果动态的追加到路由表中，router.addRoutes方法动态追加到路由表中(浏览器输入path可以看到component)
// 5.vuex管理一份路由表，同步响应菜单的显示(因为router.options.routes不是响应式的)

// 按钮的操作权控制
// 1.移除或显示(v-if="条件")
// 2.禁用（:disable="!条件"）
// 3.显示，也不禁用，给出无权操作的提示
// if (!this.$store.state.user.userInfo.roles.points.includes('point-del')) {
//   return this.$message.warning('你没有删除权限，请联系管理员')
// }

// 按钮的操作权，
// （1）3种实现思路
//    1.是否渲染（v-if）
//    2.是否禁用（：disabled属性）
//    3.代码中的逻辑判断，有权限放行，否则直接return
// （2）代码中
//     1.自定义全局指令(v-permssion)
//       判断指令绑定表达式的值是否在vuex中的用户权限点的数组中是否包含
//     2.给Vue新增原型方法($checkPermission)
//       判断方法参数值是否在vuex中用户权限点的数组中





